<?php
declare (strict_types = 1);

namespace app\api\model;

use think\Model;
use GuzzleHttp\Client;
/**
 * @mixin \think\Model
 */
class TencentMsg
{

    //SendCloud
    private static $url = 'https://sms.tencentcloudapi.com';
    private static $appid = 1400426911;
    private static $appkey = 'f172496e8f6c0daf099f3dbeb560b291';
    private static $content;
    private static $prefix = '喵美美';
    private static $context = '美妆说';
    private static $error = '';
    private static $mobiles = '';
    private static $path = '/';
    private static $secretId = 'AKIDMSMEtHmVMx1oLcNyASVAhzjV3LGD7PbX';
    private static $secretKey = 'zjQwBAsJUS9br9AvRrITP6YFhsY1DCwU';
    private static $action = 'SendSms';
    private static $requestMethod = 'GET';
    private static $requestHost = 'sms.tencentcloudapi.com';
    private static $_version = '2019-07-11';
    private static $templateId = 'login';
    public static $template = [
        'login' => 720711,//'{1}为您的登录验证码，请于{2}分钟内填写，如非本人操作，请忽略本短信。',
        'register' => 720709,//'您正在申请手机注册，验证码为：{1}，{2}分钟内有效！',
        'shop_examine_pass' => 734279,//'您开店申请已通过，管理后台：https://shopadmin.miaommei.com/admin，账号：{1}，密码：{2}；请尽快登录后台激活。',
    ];

    /**
     * 获取短信内容
     * @param array $prefix [+8613500135000,+8613500135001]
     * @return string []
     */
    public static function setContent(array $contents){
        self::$content = $contents;
        return self::class;
    }

    /**
     * 设置签名
     * @param string $prefix
     * @return string
     */
    public static function setPrefix(string $prefix) {
        self::$prefix = $prefix;
        return self::class;
    }

    /**
     * 设置接收的手机号码
     * @param array $mobiles [+8613500135000,+8613500135001]
     * @return string
     */
    public static function setMobiles(array $mobiles){
        self::$mobiles = $mobiles;
        return self::class;
    }

    /**
     * 设置保留信息
     * @param string $context
     * @return string
     */
    public static function setContext($context){
        self::$context = $context;
        return self::class;
    }

    

    /**
     * 设置模板id
     * @param string $context
     * @return string
     */
    public static function setTemplateId($templateId){
        self::$templateId = $templateId;
        return self::class;
    }

    public static function getReturn() {
        return self::$error;
    }


    /**
     * 发送短信
     * @param string $channel
     * @param int $type		1为php调用（记录短信日志），2为java调用
     * @param bool $ommit	false时发送短信验证码，true只记录不发
     * @return bool|string
     */
    public static function sendSms(){
        try{
            if(empty(self::$mobiles)) throw new \Exception('号码不正确');
            elseif(empty(self::$content)) throw new \Exception('内容不正确！！');
            $params = array(
                'Action' => self::$action,
                'Version' => self::$_version,
                'PhoneNumberSet' => self::$mobiles,
                'TemplateID' => self::$template[self::$templateId],
                'SmsSdkAppid' => self::$appid,
                'Sign' => self::$prefix,
                'TemplateParamSet' => self::$content,
                'SessionContext' => self::$context,
                'SecretId' => self::$secretId,
                'Nonce' => rand(0000,9999),
                'Timestamp' => time(),
            );
            $response = self::doRequestWithTC3(self::$action,$params,[]);
            $res = json_decode($response,true);
            WechatApiLog::insert(['type'=>2,'explain'=>'调用短信接口,phone:'.self::$mobiles[0],'request'=>json_encode($params),'response'=>json_encode($response),'status'=>$response?1:2,'add_time'=>time()]);
            if(isset($res['Response']['SendStatusSet']['Code']) && $res['Response']['SendStatusSet']['Code'] == 'Ok'){
//                fileLog(['type'=>2,'explain'=>'调用短信接口,phone:'.self::$mobiles[0],'request'=>json_encode($params),'response'=>json_encode($response),'status'=>$response?1:2,'add_time'=>time()],'test.log');
                return true;
            }
            return false;
        }catch(\Exception $e){
            self::$error = $e->getMessage();
            return false;

        }
    }

    /*
     * 原文档header头信息组装
     */
    private static function doRequestWithTC3($action, $request, $options)
    {
        $headers = array();
        $endpoint = self::$requestHost;
        $headers["Host"] = $endpoint;

        $headers["X-TC-Action"] = ucfirst($action);
//        $headers["X-TC-RequestClient"] = 'SDK_PHP_3.0.241';
        $headers["X-TC-Timestamp"] = time();
        $headers["X-TC-Version"] = self::$_version;
//        $is_region=false;
//        if ($is_region) {
//            $headers["X-TC-Region"] = 'ap-guangzhou';
//        }
        $is_token=false;
        if ($is_token) {
            $headers["X-TC-Token"] = null;//$this->getToken();
        }

        $canonicalUri = self::$path;

        $reqmethod = $method = self::$requestMethod;
        if ($reqmethod == self::$requestMethod) {
            $headers["Content-Type"] = "application/x-www-form-urlencoded";
            $rsam = self::arrayMerge($request);
            $canonicalQueryString = http_build_query($rsam);
            $payload = "";
        } else if (isset($options["IsMultipart"]) && $options["IsMultipart"] === true) {
            $boundary = uniqid();
            $headers["Content-Type"] = "multipart/form-data; boundary=".$boundary;
            $canonicalQueryString = "";
            $payload = "";//$this->getMultipartPayload($request, $boundary, $options);
        } else {
            $headers["Content-Type"] = "application/json";
            $canonicalQueryString = "";
            $payload = "";//$request->toJsonString();
        }

        if (false == true) {
            $headers["X-TC-Content-SHA256"] = "UNSIGNED-PAYLOAD";
            $payloadHash = hash("SHA256", "UNSIGNED-PAYLOAD");
        } else {
            $payloadHash = hash("SHA256", $payload);
        }
        $canonicalQueryString = urlencode(mb_convert_encoding($canonicalQueryString, 'utf-8', 'gb2312'));

        $canonicalHeaders = "content-type:".$headers["Content-Type"]."\n".
            "host:".$headers["Host"]."\n";
        $signedHeaders = "content-type;host";
        $canonicalRequest = $reqmethod."\n".
            $canonicalUri."\n".
            $canonicalQueryString."\n".
            $canonicalHeaders."\n".
            $signedHeaders."\n".
            $payloadHash;
        $algo = "TC3-HMAC-SHA256";
        // date_default_timezone_set('UTC');
        // $date = date("Y-m-d", $headers["X-TC-Timestamp"]);
        $date = gmdate("Y-m-d", $headers["X-TC-Timestamp"]);
        $service = explode(".", $endpoint)[0];
        $credentialScope = $date."/".$service."/tc3_request";
        $hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
        $str2sign = $algo."\n".
            $headers["X-TC-Timestamp"]."\n".
            $credentialScope."\n".
            $hashedCanonicalRequest;
        $skey = self::$secretKey;
        $signature = self::signTC3($skey, $date, $service, $str2sign);

        $sid = self::$secretId;
        $auth = $algo.
            " Credential=".$sid."/".$credentialScope.
            ", SignedHeaders=content-type;host, Signature=".$signature;
        $headers["Authorization"] = $auth;

        if ($reqmethod == self::$requestMethod) {
            $rsam = self::arrayMerge($request);
            $rsam['Signature'] = self::sign($rsam);
            return  curlGet(self::$url.'/?'.\GuzzleHttp\Psr7\build_query($rsam), $headers);
//            return self::getRequest(self::$path, $canonicalQueryString, $headers);
        } else {
            return false;//self::postRequestRaw(self::$path, $headers, $payload);
        }
    }


    /*
     * 多维数组转一维  原文档方法
     */
    public static function arrayMerge($array, $prepend = null)
    {
        $results = array();
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $results = array_merge($results, static::arrayMerge($value, $prepend.$key.'.'));
            }
            else {
                if (is_bool($value)) {
                    $results[$prepend.$key] = json_encode($value);
                } else {
                    $results[$prepend.$key] = $value;
                }
            }
        }
        return $results;
    }

    public static function signTC3($skey, $date, $service, $str2sign)
    {
        $dateKey = hash_hmac("SHA256", $date, "TC3".$skey, true);
        $serviceKey = hash_hmac("SHA256", $service, $dateKey, true);
        $reqKey = hash_hmac("SHA256", "tc3_request", $serviceKey, true);
        return hash_hmac("SHA256", $str2sign, $reqKey);
    }

    /*
     * 请求参数签名
     */
    public static function sign($param){
        ksort($param);
        $signStr = "GET".self::$requestHost."/?";
        foreach ( $param as $key => $value ) {
            $signStr = $signStr . $key . "=" . $value . "&";
        }
        $signStr = substr($signStr, 0, -1);

        $signature = base64_encode(hash_hmac("sha1", $signStr, self::$secretKey, true));
        return $signature;
    }

    /*
     * GuzzleHttp\Client  原文档请求方式，这里走不通
     */
    public static function getRequest($uri = '', $query = [], $headers = [])
    {
        $client = new Client(["base_uri" => self::$url]);
        $options = [
            "allow_redirects" => false,
            "timeout" => 30,
            "proxy" => null
        ];

        if ($query) {
            $options["query"] = $query;
        }

        if ($headers) {
            $options["headers"] = $headers;
        }
        return $client->get($uri, $options);
    }
}
